﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace SetupLauncher.Domain.Logic.Parameter
{
    internal class ParameterBase: IParameter
    {
        private const string CONST_INSTALLATION_PATH = @"C:\DSEPROJ\Compilados\";
        private const string CONST_CONFIG_PATH_SERVICE_INSTANCE = @"C:\DSEPROJ\Compilados\{0}\Servicos";

        Logger.ILoggable _log;
        
        public ParameterBase(Logger.ILoggable log)
        {
            _log = log;
        }

        public ParameterBase() { }

        public void CreateParameter(Entity.Product product, Entity.Environment environment, Entity.Version version, string templateFilePath)
        {
            WriteLog(string.Format("Carregando o arquivo {0}", templateFilePath));
            System.IO.File.SetAttributes(templateFilePath, System.IO.FileAttributes.Normal);

            XmlDocument xmlContent = new XmlDocument();
            xmlContent.Load(templateFilePath);

            ValidateParameter(product, environment, xmlContent);
            
            ChangeInstalationSource(product, environment, version, xmlContent);

            ChangeInstalationDestination(product, environment, version, xmlContent);
            ChangeInstalationConfigPathServiceInstance(product, environment, version, xmlContent);

            WriteLog(string.Format("Salvando o arquivo {0}", templateFilePath));
            xmlContent.Save(templateFilePath);
        }

        public void CreateConfig(Entity.Product product, Entity.Environment environment, string templateFilePath)
        {
            WriteLog(string.Format("Carregando o arquivo {0}", templateFilePath));
            System.IO.File.SetAttributes(templateFilePath, System.IO.FileAttributes.Normal);            

            XmlDocument xmlContent = new XmlDocument();
            xmlContent.Load(templateFilePath);

            ValidateConfig(product, environment, xmlContent);

            WriteLog(string.Format("Salvando o arquivo {0}", templateFilePath));
            xmlContent.Save(templateFilePath);        
        }

        protected virtual void ValidateParameter(Entity.Product product, Entity.Environment environment, XmlDocument xmlContent)
        {
            WriteLog(string.Format("Validando o arquivo"));

            XmlNode parameter = GetRootNode(xmlContent, product.Name, "Parameter");
            if (parameter == null)
                return;

            XmlNode setupConfiguration = parameter.SelectSingleNode("SetupConfiguration");
            if (setupConfiguration == null)
            {
                WriteLog("Parâmetro SetupConfiguration não encontrado");
                return;
            }

            XmlNode systemInfo = setupConfiguration.SelectSingleNode("SystemInfo");
            if (systemInfo == null)
            {
                WriteLog("Parâmetro SystemInfo não encontrado");
                return;
            }

            ValidateDataBase(systemInfo);
        }

        protected virtual void ValidateConfig(Entity.Product product, Entity.Environment environment, XmlDocument xmlContent)
        {
            WriteLog(string.Format("Validando o arquivo"));
            XmlNode config = GetRootNode(xmlContent, product.Name, "Configuration");
            if (config == null)
                return;

            XmlNode systemInfo = config.SelectSingleNode("SystemInfo");
            if (systemInfo == null)
            {
                WriteLog("Parâmetro SystemInfo não encontrado");
                return;
            }

            ValidateDataBase(systemInfo);
        }

        protected virtual void ChangeInstalationSource(Entity.Product product, Entity.Environment environment,  Entity.Version version, XmlDocument xmlContent)
        {
            XmlNode parameter = GetRootNode(xmlContent, product.Name, "Parameter");
            if (parameter != null)
            {
                string workspacePath = version.Path.Replace(@"$/", environment.WorkSpacePath + @"/").Replace(@"\", @"/") + "/x86";
                parameter.Attributes["InstalationSource"].Value = workspacePath;
            }
        }

        protected virtual void ChangeInstalationDestination(Entity.Product product, Entity.Environment environment, Entity.Version version, XmlDocument xmlContent)
        {
            XmlNode parameter = GetRootNode(xmlContent, product.Name, "Parameter");
            if (parameter != null)
            {
                parameter.Attributes["InstallationPath"].Value = CONST_INSTALLATION_PATH;
            }
        }

        protected virtual void ChangeInstalationConfigPathServiceInstance(Entity.Product product, Entity.Environment environment, Entity.Version version, XmlDocument xmlContent)
        {
            XmlNode parameter = GetRootNode(xmlContent, product.Name, "Parameter");
            if (parameter != null)
            {
                parameter.Attributes["ConfigPathServiceInstance"].Value = string.Format(CONST_CONFIG_PATH_SERVICE_INSTANCE, product.Name);
            }
        }

        private XmlNode GetRootNode(XmlDocument xmlContent, string productName, string type)
        {
            string attrib = string.Format("{0}{1}", Capitalize(productName), type);
            XmlNode parameter = xmlContent.SelectSingleNode(attrib);
            if (parameter == null)
            {
                WriteLog(string.Format("Parâmetro {0} não encontrado", attrib));
                //Gambeta...pergunte ao Cocão o motivo...
                attrib = string.Format("Setup{0}", type);
                parameter = xmlContent.SelectSingleNode(attrib);
                if (parameter == null)
                {
                    WriteLog(string.Format("Parâmetro {0} não encontrado", attrib));
                    return null;
                }
            }
            return parameter;
        }

        private string Capitalize(string text)
        {
            return string.Format("{0}{1}", text[0].ToString().ToUpper(), text.Substring(1).ToLower());
        }

        protected virtual void ValidateDataBase(XmlNode systemInfo)
        {
            XmlNode groups = systemInfo.SelectSingleNode("Groups");
            if (groups == null)
            {
                WriteLog("Parâmetro Groups não encontrado");
                return;
            }

            foreach (XmlNode database in groups.SelectNodes("Group"))
            {
                if (database.Attributes["Id"].Value.Equals("DataBase", StringComparison.CurrentCultureIgnoreCase))
                {
                    groups.RemoveChild(database);
                    break;
                }
            }
        }

        protected void WriteLog(string message)
        {
            if (_log == null)
                return;
            _log.Write(message);
        }

        protected void WriteException(string message)
        {
            if (_log == null)
                return;
            _log.WriteException(message);
        }
    }
}
